package com.jmebananas.game.state;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme.input.InputHandler;
import com.jme.renderer.pass.Pass;
import com.jme.system.DisplaySystem;
import com.jmebananas.game.console.Console;
import com.jmebananas.game.console.ConsoleListener;
import com.jmebananas.renderer.pass.AdvancedPassManager;
import com.jmebananas.renderer.pass.AdvancedRenderPass;
import com.jmebananas.renderer.pass.TileRenderPass;
import com.jmex.game.StandardGame;
import com.jmex.game.state.GameState;

/**
 * AdvancedGameState
 * 
 * @author Glenn Powell
 *
 */
public abstract class AdvancedGameState extends GameState implements ConsoleListener {

	private static final Logger logger = Logger.getLogger(AdvancedGameState.class.getName());
	

	protected boolean firstActivation = true;
	
	protected StandardGame game = null;

	protected AdvancedPassManager passManager = null;
	
	protected TileRenderPass consolePass = null;
	
	protected Console console = null;
	
	protected ArrayList<InputHandler> inputs = new ArrayList<InputHandler>();
	
	protected boolean paused = false;
	
	
	public AdvancedGameState(String name, StandardGame game) {
		this(name, game, null);
	}
	
	public AdvancedGameState(String name, StandardGame game, AdvancedPassManager passManager) {
		setName(name);
		
		this.game = game;
		this.passManager = passManager;
		if (this.passManager == null)
			this.passManager = new AdvancedPassManager();
	}
		
	public void setConsole(Console console) {
		if (consolePass == null) {
			consolePass = new TileRenderPass(AdvancedRenderPass.CONSOLE_RENDERPASS_INDEX);
			consolePass.setUpdateGeometricState(true);
			passManager.add(consolePass);
		} else {
			consolePass.remove(this.console);
		}
		
		console.addConsoleListener(this);
		consolePass.add(console);
		this.console = console;
	}
	
	public boolean isPaused() {
		return paused;
	}
	
	public void setPaused(boolean paused) {
		this.paused = paused;
	}
	
	public Console getConsole() {
		return console;
	}

	public boolean isConsoleVisible() {
		return (console != null && console.isActive());
	}

	public void setActive(boolean active) {
		super.setActive(active);
		
		if (firstActivation) {
			try {
				game.executeInGL(new Callable<Object>() {
					
					public Object call() {
						try {
							init();
							passManager.compile();
						} catch (Exception e) {
							logger.log(Level.SEVERE, "Error initializing AdvancedGameState", e);
						}
						return null;
					}
					
				});
			} catch (Exception e) {
				logger.log(Level.SEVERE, "Error initializing AdvancedGameState", e);
			}
			firstActivation = false;
		}
	}

	abstract protected void init() throws Exception;
	
	public void addPass(Pass pass) {
		passManager.add(pass);
	}
	
	public AdvancedPassManager getPassManager() {
		return passManager;
	}
	
	public void addInput(InputHandler input) {
		inputs.add(input);
	}
	
	public void consoleExecuted(Console console, String command) {
		if (command.equals("exit")) {
			shutdown();
		}
	}

	public void update(float tpf) {
		for (Iterator<InputHandler> itr = inputs.iterator(); itr.hasNext();) {
			InputHandler input = itr.next();
			input.update(tpf);
		}
		
		if (!paused) {
			passManager.updatePasses(tpf);
		}
	}

	public void render(float tpf) {
		passManager.renderPasses(DisplaySystem.getDisplaySystem().getRenderer());
	}
	
	public void shutdown() {
		game.shutdown();
	}

	public void cleanup() {
		passManager.cleanUp();
	}

}
